package com.yishoubao.demo.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author YASSER
 * @version: 1.0.0
 * @description: http请求工具类
 * @modified: <文件修改说明>
 */
public class HttpUtils {

    private final static Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    // 默认的数据编码
    private static final String DEFAULT_CHARSET = "UTF-8";

    private static final int DEFAULT_TIME_OUT = 60 * 1000;

    /**
     * 默认请求参数
     */
    private static RequestConfig DEFAULT_REQUEST_CONFIG = RequestConfig.custom()
            .setConnectTimeout(DEFAULT_TIME_OUT)   //设置连接超时时间
            .setConnectionRequestTimeout(DEFAULT_TIME_OUT) // 设置请求超时时间
            .setSocketTimeout(DEFAULT_TIME_OUT)
            .build();

    /**
     * 提交post请求
     * @param url -- 请求地址
     * @param jsonParameters --json格式的请求参数
     * @return
     */
    public static String doPost(String url, String jsonParameters) {
        HttpPost httpPost = createHttpPost(url, jsonParameters);
        String response = execute(httpPost);
        return response;
    }

    /**
     * 发起post请求并获取响应
     * @param url -- 请求地址
     * @param requestMap -- 请求form数据
     * @return
     */
    public static String doPost(String url, Map<String, String> requestMap) {
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            // 设置请求参数
            httpPost.setConfig(DEFAULT_REQUEST_CONFIG);
            // 创建请求的form数据
            List<BasicNameValuePair> basicNameValuePairList = new ArrayList<>(requestMap.size());
            for(Map.Entry<String, String> entry : requestMap.entrySet()) {
                basicNameValuePairList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            // 封装请求数据
            HttpEntity entity = new UrlEncodedFormEntity(basicNameValuePairList, DEFAULT_CHARSET);
            httpPost.setEntity(entity);

            // 创建请求执行对象
            client = HttpClients.createDefault();
            // 执行请求并获取响应
            response = client.execute(httpPost);
            // 如果
            if (response != null && response.getEntity() != null && response.getStatusLine().getStatusCode()== HttpStatus.SC_OK) {
                res = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            logger.info("向{}提交的{}执行post请求异常:{}", url, requestMap, e.getCause());
        } finally {
            closeHttp(client, response);
        }
        return res;
    }

    /**
     * 发起get请求
     * @param url
     * @return
     */
    public static String doGet(String url) {
        return doGet(url, null);
    }

    /**
     * 发起get请求
     * @param baseUrl -- 请求地址，不带参数
     * @param requestMap -- 请求参数
     * @return
     */
    public static String doGet(String baseUrl, Map<String, String> requestMap) {
        String response = null;
        try {
            URIBuilder builder = new URIBuilder(baseUrl);
            if(requestMap != null){
                Set<String> set = requestMap.keySet();
                for(String key: set){
                    builder.setParameter(key, requestMap.get(key));
                }
            }
            HttpGet httpGet = new HttpGet(builder.build());
            response = execute(httpGet);
        } catch (Exception e){
            logger.warn("向:{}发起Get请求:{}异常:{}", baseUrl, requestMap, e);
        }
        return response;
    }


    /**
     * 创建post请求对象
     * @param url -- 请求地址
     * @param jsonParameters -- json格式的请求参数
     * @return
     */
    private static HttpPost createHttpPost(String url, String jsonParameters) {
        HttpPost httpPost = new HttpPost(url);
        // 设置请求参数
        httpPost.setConfig(DEFAULT_REQUEST_CONFIG);
        StringEntity entityParams = new StringEntity(jsonParameters, ContentType.APPLICATION_JSON);
        httpPost.setEntity(entityParams);
        return httpPost;
    }

    /**
     * 执行请求，并获取响应数据
     * @param httpRequestBase
     * @return
     */
    private static String execute(HttpRequestBase httpRequestBase) {
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            // 创建请求执行对象
            client = HttpClients.createDefault();
            // 执行请求并获取响应
            response = client.execute(httpRequestBase);
            // 如果
            if (response != null && response.getEntity() != null && response.getStatusLine().getStatusCode()== HttpStatus.SC_OK) {
                res = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            logger.info("向{}提交的{}执行post请求异常:{}", httpRequestBase.getURI(), e.getCause());
        } finally {
            closeHttp(client, response);
        }
        return res;
    }


    /**
     * 关闭连接
     * @param client
     * @param response
     */
    private static void closeHttp(CloseableHttpClient client, CloseableHttpResponse response) {
        try {
            if (client != null) {
                client.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (Exception e) {
        }
    }

    public static void main(String[] args) {
        Map<String, String> requestMap = new HashMap<>(4);
        requestMap.put("merCode", "98001");
        requestMap.put("orderNo", "000000001");
        requestMap.put("orderAmount", "1.00");
        requestMap.put("realPayAmount", "1.01");
        String response = doPost("http://localhost:80/v2/test/handleNotify", requestMap);
        System.out.println(response);
    }


}
